package com.shareware.common.utils

import androidx.annotation.Keep
import com.shareware.common.debugGlobal
import com.tencent.mars.xlog.Log
import java.util.Locale

/**
 * desc: 功能描述
 * email: mobiledeveloper@qq.com
 */

private const val SUFFIX_JAVA = ".java"
private const val SUFFIX_KOTLIN = ".kt"
private const val LOG_STACK_INDEX = 5
const val LOG_METHOD_NAME = "log"
private const val MAX_LENGTH = 1500

enum class LogType {
    LEVEL_VERBOSE,
    LEVEL_DEBUG,
    LEVEL_INFO,
    LEVEL_WARNING,
    LEVEL_ERROR,
    LEVEL_FATAL,
    LEVEL_NONE
}

/**
 * 热修复生成wrapContent代码错误，故keep住，不参与混淆
 */
@JvmOverloads
@Keep
fun log(tag: String, message: String?, type: LogType = LogType.LEVEL_DEBUG) {
    if (!debugGlobal) {
        return
    }
    val wrapMessage = wrapContent(message)
    val splitCount = wrapMessage.length / MAX_LENGTH
    if (splitCount > 0) {
        var split = 0
        for (index in 0 until splitCount) {
            val nextLength = split + MAX_LENGTH
            logPrint(tag, wrapMessage.substring(split, nextLength), type)
            split = nextLength
        }
        logPrint(tag, wrapMessage.substring(split), type)
    } else {
        logPrint(tag, wrapMessage, type)
    }
}

private fun logPrint(tag: String, message: String, type: LogType) {
    when (type) {
        LogType.LEVEL_DEBUG -> {
            Log.d(tag, message)
        }

        LogType.LEVEL_INFO -> {
            Log.i(tag, message)
        }

        LogType.LEVEL_ERROR -> {
            Log.e(tag, message)
        }

        LogType.LEVEL_WARNING -> {
            Log.w(tag, message)
        }

        else -> {
            Log.v(tag, message)
        }
    }
}

fun flushXLog(isSync: Boolean) {
    Log.appenderFlush(isSync)
}

fun logStackTrace(tag: String, ex: Throwable) {
    Log.printErrStackTrace(tag, ex, "")
}

fun logFormat(tag: String, format: String, vararg args: Any) {
    log(tag, format.format(Locale.getDefault(), *args))
}

private fun wrapContent(message: String?): String {
    val stackTrace = Thread.currentThread().stackTrace
    var targetElement = stackTrace[LOG_STACK_INDEX]
    if (targetElement.methodName == LOG_METHOD_NAME) {
        targetElement = stackTrace[LOG_STACK_INDEX + 1]
    }
    val suffix =
        if (targetElement.fileName != null && targetElement.fileName!!.endsWith(SUFFIX_KOTLIN)) {
            SUFFIX_KOTLIN
        } else {
            SUFFIX_JAVA
        }
    var className = targetElement.className
    val classNameInfo = className.split(Regex("\\."))
    if (classNameInfo.isNotEmpty()) {
        className = classNameInfo[classNameInfo.size - 1] + suffix
    }
    if (className.contains("$")) {
        className = className.split(Regex("\\$"))[0] + suffix
    }
    return "[($className:${targetElement.lineNumber})#${targetElement.methodName}]:$message"
}